package com.custom.customswitchbutton;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;

import androidx.annotation.Nullable;

/**
 * @description：TODO
 * @Author MRyan
 * @Date 2020/3/12 13:14
 * @Version 1.0
 */
public class CustomSwitchButton extends View implements View.OnClickListener {
    private float switchViewStrockWidth;
    private int mSwitchViewBgColor;
    private int mSwitchViewBallColor;
    private Paint mBallPaint;
    private Paint mBgPaint;
    private int mViewHeight;
    private int mViewWidth;
    private int mStrokeRadius;
    private float mSolidRadius;
    private RectF mBgStrokeRectF;
    private State mCurrentState;
    private float mSwitchBallx;
    private int BALL_X_RIGHT;
    private int GrayColor;

    public enum State {//枚举变量用于打开关闭的状态选择
        OPEN, CLOSE
    }

    public CustomSwitchButton(Context context) {
        super(context);
    }

    public CustomSwitchButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, 0);
    }


    public CustomSwitchButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initAttr(context, attrs);
        initData();
    }

    private void initData() {
        mCurrentState = State.CLOSE;
        mBallPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBallPaint.setAntiAlias(true);
        mBallPaint.setColor(mSwitchViewBallColor);
        mBallPaint.setStyle(Paint.Style.FILL);
        mBallPaint.setStrokeWidth(2);
        mBallPaint.setStrokeCap(Paint.Cap.ROUND);
        mBallPaint.setStrokeJoin(Paint.Join.ROUND);

        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        mBgPaint.setColor(GrayColor);
        mBgPaint.setStyle(Paint.Style.FILL);
        mBgPaint.setStrokeWidth(2);
        mBgPaint.setStrokeCap(Paint.Cap.ROUND);
        mBgPaint.setStrokeJoin(Paint.Join.ROUND);
        setOnClickListener(this);

    }

    private void initAttr(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitchButton);
        mSwitchViewBgColor = typedArray.getColor(R.styleable.CustomSwitchButton_SwitchViewBgColor, mSwitchViewBgColor);
        mSwitchViewBallColor = typedArray.getColor(R.styleable.CustomSwitchButton_SwitchViewBallColor, mSwitchViewBallColor);
        GrayColor = typedArray.getColor(R.styleable.CustomSwitchButton_SwitchViewBgBotColor, GrayColor);
        typedArray.recycle();
        mViewHeight = dptopx(context, 30);
        mViewWidth = dptopx(context, 60);

    }


    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(mViewWidth, mViewHeight);
        mBgStrokeRectF = new RectF(0, 0, mViewWidth, mViewHeight);
        switchViewStrockWidth = mViewWidth / 18;
        mStrokeRadius = mViewHeight / 2 + 7;
        mSolidRadius = (mViewHeight - 2 * switchViewStrockWidth) / 2;
        mSwitchBallx = mViewHeight / 2;
        BALL_X_RIGHT = mViewWidth - mStrokeRadius;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRoundRect(mBgStrokeRectF, 60, 60, mBgPaint);
        canvas.drawCircle(mSwitchBallx, mViewHeight / 2, mSolidRadius, mBallPaint);
    }


    @Override
    public void onClick(View v) {
        mCurrentState = (mCurrentState == State.CLOSE ? State.OPEN : State.CLOSE);
        if (mCurrentState == State.OPEN) {
            animate((int) mStrokeRadius, BALL_X_RIGHT, GrayColor, mSwitchViewBgColor);
        } else {
            animate(BALL_X_RIGHT, (int) mStrokeRadius, mSwitchViewBgColor, GrayColor);
        }
        if (onChangeBsvListener != null) {
            if (mCurrentState == State.OPEN) {
                onChangeBsvListener.onChangeBsv(true);
            } else {
                onChangeBsvListener.onChangeBsv(false);
            }
        }
    }

    private void animate(int from, int to, int startColor, int endColor) {
        ValueAnimator translate = ValueAnimator.ofFloat(from, to);
        translate.setInterpolator(new AccelerateInterpolator());
        translate.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mSwitchBallx = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        ValueAnimator color = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
        color.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            private int BgColor;

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                BgColor = ((int) animation.getAnimatedValue());
                mBgPaint.setColor(BgColor);
                postInvalidate();
            }
        });
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(translate, color);
        animatorSet.setDuration(200);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                setClickable(true);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                setClickable(false);
            }
        });
        animatorSet.start();
    }

    public interface OnChangeBsvListener {
        void onChangeBsv(boolean isState);
    }

    private OnChangeBsvListener onChangeBsvListener;

    public void setOnChangeBsvListener(OnChangeBsvListener onChangeBsvListener) {
        this.onChangeBsvListener = onChangeBsvListener;
    }

    public int dptopx(Context context, float value) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (value * scale + 0.5);
    }
}
